<style>

@media (max-width: 768px) {
    .code-generation-box > span {
        line-height: 40px;
    }

    .span-hsiang-hsien {
        display: block;
    }
}

@media screen and (min-width: 768px) {
    .span-hsiang-hsien {
        margin-left: 20px;
    }
}

</style>

<template>
    <div>
        <el-card class="el-card__body">
            <div class="code-generation-box">
                <span class="span-hsiang-hsien" style="margin-left: 0px">
                    <label>数据源: </label>
                    <!--<span>选择数据源</span>-->
                    <el-select style="width: 180px" v-model="dataSourceId" :clearable="true" filterable placeholder="选择数据源, 默认当前服务" @change="datasourceChange()">
                        <el-option
                            v-for="item in datasourceDic"
                            :key="item.id"
                            :label="item.dbTitle"
                            :value="item.id">
                        </el-option>
                    </el-select>
               </span>
                <span class="span-hsiang-hsien">
                 当前表: <span style="color: var(--el-color-primary)"> {{ treeRowData.name }} - {{ treeRowData.comment }}</span>
                </span>
                <span class="span-hsiang-hsien">
                       <!--  当前数据源: <font color="#ff69b4"> {{datasource.dbName}} - {{datasource.dbTitle}}</font> -->
                            <span> 自关联表:
                            <el-switch
                                v-model="search.isTree"
                                active-color="#13ce66"
                                inactive-color="#ff4949"
                                active-text="是"
                                inactive-text="否">
                               </el-switch><span class="span-hsiang-hsien" style="color: var(--el-color-primary);font-size: 12px;"> 开启自关联将生成左导航树</span>
               </span>
               <span class="span-hsiang-hsien">
                    <span>vue 版本指定: </span>
                    <span>
                         <el-select style="width: 200px" v-model="search.vueVersion" placeholder="请选择">
                           <el-option
                               v-for="item in vueVersionsOptions"
                               :key="item.value"
                               :label="item.label"
                               :value="item.value">
                           </el-option>
                       </el-select>
                    </span>
                </span>
              </span>
            </div>
        </el-card>

        <!--    表格开启   -->
        <el-card class="xj-table">
            <div class="xj-table-tree">
                <!-- 左边媒体分类树结构数据 -->
                <el-card style="width: 98%;height:600px;overflow:auto;margin-top: -12px">
                    <!-- 数据表 -->
                    <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick"></avue-tree>
                </el-card>
            </div>
            <div class="xj-table-list">
                <!-- crud -->
                <avue-crud ref="crudField"
                           :data="data"
                           :option="option"
                           v-model:page="page"
                           v-model:search="search"
                           :table-loading="loading"
                           @on-load="onLoad"
                           @refresh-change="onLoad"
                           @selection-change="selectionChange"
                           @search-change="searchChange"
                           @row-click="handleRowClick">
                    <template #menu-left="{size}">
                        <span><!--  防抖动--> </span>
                        <el-button type="primary" :size="size" plain @click="dbDatasource()">数据源管理</el-button>
                        <el-button type="primary" :size="size" plain @click="finDGenerateGetPath()">查看生成路径</el-button>
                        <el-button type="primary" :size="size" plain @click="findGeneratePreview()">生成预览代码 (在线查看)</el-button>
                        <el-button type="primary" :size="size" plain @click="generateCodeJava()">生成后端代码</el-button>
                        <el-button type="primary" :size="size" plain @click="generateCodeVueFun()">生成并下载 (vue)</el-button>
                        <el-button type="primary" :size="size" plain @click="generateCodeJavaAndVueFun()">生成并下载 (all)</el-button>
                    </template>
                    <!-- 数据类型 -->
                    <template #vueFieldType="{size,row,index}">
                        <!--<el-col :span="6">-->
                        <!--  <avue-select v-model="row.vueFieldType" placeholder="请选择内容" type="tree" :dic="vueFieldTypeDic"></avue-select>-->

                        <el-select v-model="row.vueFieldType" filterable placeholder="请选择" @change="vueFieldTypeChange(row)">
                            <el-option
                                v-for="item in vueFieldTypeDic"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value"
                                :disabled="item.disabled"
                            >
                            </el-option>
                        </el-select>
                        <!-- </el-col>-->
                    </template>

                    <!-- 字典
                          // 单选-(radio)                 4
                          // 多选-(checkbox)              5
                          // 下拉选择-(select-单选)        6
                          // 下拉选择 (select-单选+搜索)    7
                          // 下拉选择 (select-多选+搜索)    8
                          // 开关-(switch)                 9
                    -->
                    <template #dictCode="{size,row,index}">
                        <el-cascader v-if="isVueFieldTypeDict(row)"
                                     v-model="row.dictCode"
                                     placeholder="试试搜索：性别"
                                     filterable
                                     clearable
                                     :show-all-levels="false"
                                     :options="dictCodeOption"
                                     @change="handleChange"
                                     :props="dictCodeProps"
                        ></el-cascader>
                    </template>

                    <!-- 是否是搜索参数 -->
                    <template #isSearch="{size,row,index}">
                        <el-switch v-model="row.isSearch"
                                   :active-value=true :inactive-value=false
                                   active-text="" inactive-text=""
                                   @change="isSearchChange"
                        >
                        </el-switch>
                    </template>
                </avue-crud>
            </div>
        </el-card>
        <el-dialog draggable title="查看生成路径" v-if="findPageDialogVisible" v-model="findPageDialogVisible" top="6vh" width="60%">
            <Paths :generatePaths="generatePaths"></Paths>
            <span slot="footer" class="dialog-footer"></span>
        </el-dialog>
        <el-dialog draggable title="生成代码预览" v-if="generateCodePreviewDialogVisible" v-model="generateCodePreviewDialogVisible" top="6vh" width="80%">
            <CodePreview :generateCodePreviews="generateCodePreviews"></CodePreview>
            <span slot="footer" class="dialog-footer"></span>
        </el-dialog>
    </div>
</template>


<script>

import router from '@/router/'
import {defineAsyncComponent} from 'vue';

export default {
    components: {
        Paths: defineAsyncComponent(() => import('./generatePaths.vue')),
        CodePreview: defineAsyncComponent(() => import('./generateCodePreview.vue'))
    },
    data() {
        return {
            uri: {
                infoFieldList: "/api/admin/gc/dataBase/table/field",  // 根据字段查询表字段
                infoTableList: "/api/admin/gc/dataBase/table/list",   // 所有表
                generateGetPath: "/api/admin/gc/generate/getPath",    // 代码生成路径
                generatePreview: "/api/admin/gc/generate/preview",    // 生成预览代码
                generateCode: "/api/admin/gc/generate/generateCode",   // 生成代码
                generateCodeVue: "/api/admin/gc/generate/generateCodeVue", // 只生成vue代码(直接下载)
                generateCodeJavaAndVue: "/api/admin/gc/generate/generateCodeJavaAndVue", // 生成java + vue代码(直接下载)
                diceFindList: "/api/admin/sys/dictionary/tree", // 获取字典数据
                datasourceInfoList: "/api/admin/gc/datasource/findPage?size=10000",   // 查询数据源
            },
            loading: true,
            dialogWidth: "60%",
            findPageDialogVisible: false,
            generateCodePreviewDialogVisible: false,
            updDialogVisible: false,
            page: this.website.pageParams,
            search: {
                tableName: "t_basic",
                isTree: false,
                vueVersion: "vue3"
            },
            data: [],
            rowData: {},
            option: {},
            generatePaths: {},         // 代码生成路径数据
            generateCodePreviews: {},  // 预览代码数据
            vueFieldTypeDic: this.dict.get(this.website.Dict.Base.VueFieldType),  // 字段类型选择数据

            // 数据源
            datasourceDic: [],
            dataSourceId: null,
            // 数据表
            treeRowData: {name: "t_basic", comment: "系统通用字段表"},
            treeData: [],
            treeOption: {
                defaultExpandAll: false,
                filter: true,
                addBtn: false,
                props: {
                    labelText: '数据表',
                    label: 'name',
                    value: 'name',
                    children: ''
                }
            },
            // 字段上字典值
            dictCodeOption: [],
            dictCodeProps: {
                expandTrigger: "hover",   // 点击进入二级还是鼠标移动进入 click / hover
                // filterable : true,        // 是否可搜索
                // "show-all-levels" : false, // 是否显示完整路径
                value: "code",
                label: "name",
                children: "children",
            },
            vueVersionsOptions: [{
                value: 'vue3',
                label: 'vue3'
            }, {
                value: 'vue2',
                label: 'vue2'
            }],
        }
    },
    mounted() {
        this.option = JSON.parse(JSON.stringify(this.website.optionConfig));
        this.option.index = false;
        this.option.menu = false;
        this.option.rowKey = "id";
        this.option.maxHeight = 600;
        // 开启多选
        this.option.selection = true;
        this.option.reserveSelection = true;
        this.option.column = [
            {
                label: '字段名',
                prop: 'name',
                align: 'left',
                // width: 200,
                // width: 200,
            },
            {
                label: '字段类型(长度)',
                prop: 'typeDetail',
                align: 'left',
            },
            {
                label: '字段描叙',
                prop: 'desc',
                align: 'left',
                overHidden: true
            },
            {
                label: 'vue表单类型',
                prop: 'vueFieldType',
            },
            {
                label: '选择字典',
                prop: 'dictCode',
                align: 'left',
                // width: 240,
            },
            {
                label: '是否搜索 (eq/like)',
                prop: 'isSearch',
                align: 'left',
            },
            {
                label: '是否允许空 (mysql)',
                prop: 'isNull',
                align: 'left',
            },
            {
                label: '默认值 (mysql)',
                prop: 'defaultVal',
                align: 'left',
            },

        ]
    },
    created() {


        // vue 需要使用到字典的字段拉出字典选择
        this.crud.get(this.uri.diceFindList).then((res) => {
            // 直接取 dictList , 不要第一级
            this.dictCodeOption = res.data.data;
        });

        // 查询数据源
        this.crud.get(this.uri.datasourceInfoList).then((res) => {
            this.datasourceDic = res.data.data.records;
        });

        // 查询数据表
        this.findTableList();
    },
    activated: function () {
        this.crud.doLayout(this, this.$refs.crudField)
    },
    methods: {
        onLoad() {
            this.loading = true;
            this.crud.get(this.uri.infoFieldList, {
                tableName: this.search.tableName,
                dataSourceId: this.dataSourceId
            }).then((res) => {
                // 默认文本
                res.data.data.forEach((item) => {
                    // 处理默认选中类型 ( 数字: int|bigint|double|float|decimal  时间: date|datetime 单选: tinyint 其他默认文本)
                    item.vueFieldType = 1;
                    if (item.type === "int" || item.type === "bigint" || item.type === "double" || item.type === "float" || item.type === "decimal") {
                        // 数字
                        item.vueFieldType = 2;
                    } else if (item.type === "tinyint") {
                        // 单选
                        item.vueFieldType = 4;
                    } else if (item.type === "date" || item.type === "datetime") {
                        // 时间
                        item.vueFieldType = 11;
                    }
                });

                this.data = res.data.data;
                this.checkeds();
                this.loading = false;
            })
        },


        /**
         * 查询数据表
         */
        findTableList() {
            // 查询数据表
            this.crud.get(this.uri.infoTableList, {dataSourceId: this.dataSourceId}).then((res) => {
                this.treeData = res.data.data;
            });
        },

        searchChange(params, done) {
            this.page.currentPage = 1;
            this.onLoad();
            done();
        },
        handleRowClick(row) {
            this.rowData = JSON.parse(JSON.stringify(row));
        },
        // 加载数据处理复选选中数据处理（调用 toggleSelection 后会自动触发 selectionChange）
        checkeds() {
            this.$nextTick(function () {
                this.$refs.crudField.clearSelection();
                this.data.forEach(row => {
                    if (row.isChecked) {
                        this.$refs.crudField.toggleRowSelection(row, true);
                    }
                });
            })
        },

        // 选择数据表  查询刷新字段表数据
        nodeClick(data) {
            this.treeRowData = data;
            this.search.tableName = data.name;
            this.onLoad();
            //this.$message.success(JSON.stringify(data))
        },
        // 选中的复选字段，给所有数据处理当前 isChecked 参数
        selectionChange(list) {
            this.$nextTick(function () {
                let checkednNames = list.map(item => item.name);
                console.debug(checkednNames)
                for (const row of this.data) {
                    // 包含=true, 不包含=false
                    row.isChecked = checkednNames.includes(row.name)
                }
            })
        },
        // 获取代码生成路径
        finDGenerateGetPath() {
            this.crud.get(this.uri.generateGetPath, {
                tableName: this.search.tableName,
                dataSourceId: this.dataSourceId,
            }).then((res) => {
                this.generatePaths = res.data.data;
                this.findPageDialogVisible = true;
            })
        },
        // 生成预览代码
        findGeneratePreview() {
            let data = {
                tableComment: this.treeRowData.comment,
                tableName: this.search.tableName,
                dataSourceId: this.dataSourceId,
                vueVersion: this.search.vueVersion,
                isTree: this.search.isTree,
                data: JSON.stringify(this.data)
            };
            this.crud.post(this.uri.generatePreview, data).then((res) => {
                for (var k in res.data.data) {
                    res.data.data[k] = res.data.data[k] + "?" + Date.now();
                }
                this.generateCodePreviews = res.data.data;
                this.generateCodePreviewDialogVisible = true;
            })
        },
        // 生成后端代码（生成到项目）
        generateCodeJava() {
            this.$confirm(`生成服务端代码, 如果重新生成将覆盖原数据, 是否继续?`, '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                let data = {
                    tableComment: this.treeRowData.comment,
                    tableName: this.search.tableName,
                    dataSourceId: this.dataSourceId,
                    vueVersion: this.search.vueVersion,
                    isTree: this.search.isTree,
                    data: JSON.stringify(this.data)
                };
                this.crud.post(this.uri.generateCode, data).then(() => {
                    this.$message.success("代码生成成功");
                })
            })
        },
        // 生成vue代码（下载）
        generateCodeVueFun() {
            let data = {
                tableComment: this.treeRowData.comment,
                tableName: this.search.tableName,
                vueVersion: this.search.vueVersion,
                dataSourceId: this.dataSourceId,
                isTree: this.search.isTree,
                data: JSON.stringify(this.data)
            };
            this.crud.download(this.uri.generateCodeVue, data);
        },
        // 生成java + vue代码（下载）
        generateCodeJavaAndVueFun() {
            let data = {
                tableComment: this.treeRowData.comment,
                tableName: this.search.tableName,
                vueVersion: this.search.vueVersion,
                dataSourceId: this.dataSourceId,
                isTree: this.search.isTree,
                data: JSON.stringify(this.data),
            };
            this.crud.download(this.uri.generateCodeJavaAndVue, data);
        },
        /**
         * 打开数据源管理
         * @author wangsong
         * @date 2022/8/9 13:42
         * @return
         */
        dbDatasource() {
            router.push({path: "/gc/db"});
        },

        /**
         * 选择字段类型
         * @param row
         */
        vueFieldTypeChange(row) {
            if (this.isVueFieldTypeDict(row)) {
                // 判断是否可用字典，可用且没有选择的话设置默认字典类型
            } else {
                // 不可用清除字典数据
                row.dictCode = null;
            }
            this.checkeds();
        },

        /**
         * 字典选择监听
         */
        handleChange(value) {
            this.checkeds()
            console.debug(value);
        },
        /**
         * 是否搜索选择监听
         */
        isSearchChange(value) {
            this.checkeds();
            console.debug(value);
        },


        /**
         * 判断字段是否需要使用字典
         */
        isVueFieldTypeDict(row) {
            if (row.vueFieldType >= 4 && row.vueFieldType <= 9) {
                return true;
            }
            return false;
        },

        /**
         * 数据源选择
         */
        datasourceChange() {
            console.debug("切换数据源:" + this.dataSourceId);
            this.findTableList();
        }
    }
}
</script>


<style>
.text {
    font-size: 14px;
}

.item {
    margin-bottom: 18px;
}

.clearfix:before,
.clearfix:after {
    display: table;
    content: "";
}

.clearfix:after {
    clear: both
}

.box-card {
    width: 100%;
}
</style>

